module soc_esfr 
(	ESFRDI,
  	SFRSA,
	DESTIN_A,
	SFRWE,
	SFRRE,
	DESTIN_DO,
	XINTR_SRC,
	XINTR_ACK,
	CLK,
	RESET,
	CANSEL,

	spi_sck,
	spi_mosi,
	spi_miso,
	spi_sck_nen,
	spi_mosi_nen,

	spi2_sck,
	spi2_mosi,
	spi2_miso,
	spi2_sck_nen,
	spi2_mosi_nen,

	can_rx_i,
	can_tx_o,
	can_tx_nen,

	can2_rx_i,
	can2_tx_o,
	can2_tx_nen,

	i2c_scl_pad_i,
	i2c_scl_pad_o,
	i2c_scl_padoen_o,
	i2c_sda_pad_i,
	i2c_sda_pad_o,
	i2c_sda_padoen_o,

	pwmout_0,
	pwmout_0_nen,
	pwmout_1,
	pwmout_1_nen,
	pwmout_2,
	pwmout_2_nen,
	pwmout_3,
	pwmout_3_nen,

	uart_rx,
	uart_tx,
	uart_tx_nen
);

input		   CANSEL;
output	[7:0]  ESFRDI;
input   [6:0]  SFRSA;
input	[7:0]  DESTIN_A;
input		   SFRWE;
input		   SFRRE;
input   [7:0]  DESTIN_DO;
output	[13:0] XINTR_SRC;
input	[13:0] XINTR_ACK;
input		   CLK;
input		   RESET;

output		spi_sck;
output		spi_mosi;
input		spi_miso;
output		spi_sck_nen;
output		spi_mosi_nen;

output		spi2_sck;
output		spi2_mosi;
input 		spi2_miso;
output		spi2_sck_nen;
output		spi2_mosi_nen;

input		can_rx_i;
output		can_tx_o;
output		can_tx_nen;

input		can2_rx_i;
output		can2_tx_o;
output		can2_tx_nen;

input		i2c_scl_pad_i;
output		i2c_scl_pad_o;
output		i2c_scl_padoen_o;
input		i2c_sda_pad_i;
output		i2c_sda_pad_o;
output		i2c_sda_padoen_o;

output		pwmout_0;
output		pwmout_1;
output		pwmout_2;
output		pwmout_3;
output		pwmout_0_nen;
output		pwmout_1_nen;
output		pwmout_2_nen;
output		pwmout_3_nen;

input		uart_rx;
output		uart_tx;
output		uart_tx_nen;

//uart esfr
reg	[7:0] 		uart_read_addr;
reg [7:0] 		uart_write_addr;
wire	 		cs_uart;
reg				cs_read_uart;
reg				cs_write_uart;
wire 	[7:0]	uart_data_out;
wire			uart_we;

wire			uart_rx;
wire			uart_tx;

reg				uart_tx_q;
wire			uart_tx_nen;

//generate delay signal
always @(posedge CLK, posedge RESET)
begin
	if(RESET)
		uart_tx_q <= 1;
	else
		uart_tx_q <= uart_tx;
end

assign	uart_tx_nen = uart_tx && uart_tx_q;

assign	uart_we = cs_write_uart && SFRWE;
assign	cs_uart = cs_read_uart | cs_write_uart;

uart_top UART_ESFR(
	.clk(CLK),
	.rst(RESET),
	.cs(cs_uart),
	.wr(uart_we),
	.rd(SFRRE),
	.read_addr(uart_read_addr),
	.write_addr(uart_write_addr),
	.data_in(DESTIN_DO),
	.data_out(uart_data_out),
	.int_o(XINTR_SRC[4]),

	.stx_o(uart_tx),
	.srx_i(uart_rx)
);
	
always @(*)
begin
	case (DESTIN_A)
	  8'h84:begin
	  		uart_write_addr = 8'h0;
			cs_write_uart = 1;end
	  8'h85:begin
	  		uart_write_addr = 8'h1;
			cs_write_uart = 1;end
	  8'h86:begin
	  		uart_write_addr = 8'h2;
			cs_write_uart = 1;end
	  8'h98:begin
	  		uart_write_addr = 8'h3;
			cs_write_uart = 1;end
	  8'h99:begin
	  		uart_write_addr = 8'h4;
			cs_write_uart = 1;end
	  8'hA1:begin
	  		uart_write_addr = 8'h5;
			cs_write_uart = 1;end
	default: begin
			uart_write_addr = 8'h0;
			cs_write_uart = 0;end
	endcase
end

always @(*)
begin
	case ({1'b1,SFRSA})
	  8'h84:begin
	  		uart_read_addr = 8'h0;
			cs_read_uart = 1;end
	  8'h85:begin
	  		uart_read_addr = 8'h1;
			cs_read_uart = 1;end
	  8'h86:begin
	  		uart_read_addr = 8'h2;
			cs_read_uart = 1;end
	  8'h98:begin
	  		uart_read_addr = 8'h3;
			cs_read_uart = 1;end
	  8'h99:begin
	  		uart_read_addr = 8'h4;
			cs_read_uart = 1;end
	  8'hA1:begin
	  		uart_read_addr = 8'h5;
			cs_read_uart = 1;end
	default: begin
			uart_read_addr = 8'h0;
			cs_read_uart = 0;end
	endcase
end

//SPI1 ESFR
reg	[1:0] spi_read_addr;
reg	[1:0] spi_write_addr;
wire		  cs_spi;
reg		  cs_read_spi;
reg		  cs_write_spi;
wire	[7:0] spi_data_out;
wire		  spi_we;

wire		  spi_sck;
wire		  spi_mosi;
wire		  spi_miso;

reg			  spi_sck_q;
reg			  spi_mosi_q;

wire		  spi_sck_nen;
wire		  spi_mosi_nen;

//gegerate delay signal
always @(posedge CLK, posedge RESET)
begin
	if (RESET)
	begin
		spi_sck_q <= 1;
		spi_mosi_q <= 1;
	end
	else
	begin
		spi_sck_q <= spi_sck;
		spi_mosi_q <= spi_mosi;
	end
end

assign	spi_sck_nen = spi_sck && spi_sck_q;
assign	spi_mosi_nen = spi_mosi && spi_mosi_q;

assign spi_we = cs_write_spi & SFRWE;
assign cs_spi = cs_read_spi | cs_write_spi;

spi_top SPI_ESFR (		 .clk_i(CLK),
						 .rst_i(RESET),
						 .cs_i(cs_spi),
						 .write_addr_i(spi_write_addr),
						 .read_addr_i(spi_read_addr),
						 .data_in(DESTIN_DO),
						 .data_out(spi_data_out),
						 .wr_i(spi_we),
						 .rd_i(SFRRE),
						 .irq_o(XINTR_SRC[6]),

						 .sck_o(spi_sck),
						 .mosi_o(spi_mosi),
						 .miso_i(spi_miso)
						);

always @(*)		//spi decode write address
begin
	case (DESTIN_A)
	  8'h8E:begin
	  		spi_write_addr = 2'h0;
			cs_write_spi = 1; end
	  8'h8F:begin
	  		spi_write_addr = 2'h1;
			cs_write_spi = 1; end
	  8'h91:begin
	  		spi_write_addr = 2'h2;
			cs_write_spi = 1; end
	  8'h92:begin
	  		spi_write_addr = 2'h3;
			cs_write_spi = 1; end
	  default: begin
	  		spi_write_addr = 2'h0;
			cs_write_spi = 0; end
	endcase
end

always @(*)		//spi decode read address
begin
	case ({1'b1,SFRSA})
	  8'h8E:begin
	  		spi_read_addr = 2'h0;
			cs_read_spi = 1; end
	  8'h8F:begin
	  		spi_read_addr = 2'h1;
			cs_read_spi = 1; end
	  8'h91:begin
	  		spi_read_addr = 2'h2;
			cs_read_spi = 1; end
	  8'h92:begin
	  		spi_read_addr = 2'h3;
			cs_read_spi = 1; end
	  default: begin
	  		spi_read_addr = 2'h0;
			cs_read_spi = 0; end
	endcase
end

//SPI2 ESFR
reg	[1:0] spi2_read_addr;
reg	[1:0] spi2_write_addr;
wire		  cs_spi2;
reg		  cs_read_spi2;
reg		  cs_write_spi2;
wire	[7:0] spi2_data_out;
wire		  spi2_we;

wire		  spi2_sck;
wire		  spi2_mosi;
wire		  spi2_miso;

reg			  spi2_sck_q;
reg			  spi2_mosi_q;

wire		  spi2_sck_nen;
wire		  spi2_mosi_nen;

assign spi2_we = cs_write_spi2 & SFRWE;
assign cs_spi2 = cs_read_spi2 | cs_write_spi2;

spi_top SPI2_ESFR (		 .clk_i(CLK),
						 .rst_i(RESET),
						 .cs_i(cs_spi2),
						 .write_addr_i(spi2_write_addr),
						 .read_addr_i(spi2_read_addr),
						 .data_in(DESTIN_DO),
						 .data_out(spi2_data_out),
						 .wr_i(spi2_we),
						 .rd_i(SFRRE),
						 .irq_o(XINTR_SRC[7]),

						 .sck_o(spi2_sck),
						 .mosi_o(spi2_mosi),
						 .miso_i(spi2_miso)
						);

//gegerate delay signal
always @(posedge CLK, posedge RESET)
begin
	if (RESET)
	begin
		spi2_sck_q <= 1;
		spi2_mosi_q <= 1;
	end
	else
	begin
		spi2_sck_q <= spi2_sck;
		spi2_mosi_q <= spi2_mosi;
	end
end

assign	spi2_sck_nen = spi2_sck && spi2_sck_q;
assign	spi2_mosi_nen = spi2_mosi && spi2_mosi_q;



always @(*)		//spi2 decode write address
begin
	case (DESTIN_A)
	  8'h93:begin
	  		spi2_write_addr = 2'h0;
			cs_write_spi2 = 1; end
	  8'h94:begin
	  		spi2_write_addr = 2'h1;
			cs_write_spi2 = 1; end
	  8'h95:begin
	  		spi2_write_addr = 2'h2;
			cs_write_spi2 = 1; end
	  8'h96:begin
	  		spi2_write_addr = 2'h3;
			cs_write_spi2 = 1; end
	  default: begin
	  		spi2_write_addr = 2'h0;
			cs_write_spi2 = 0; end
	endcase
end

always @(*)		//spi2 decode read address
begin
	case ({1'b1,SFRSA})
	  8'h93:begin
	  		spi2_read_addr = 2'h0;
			cs_read_spi2 = 1; end
	  8'h94:begin
	  		spi2_read_addr = 2'h1;
			cs_read_spi2 = 1; end
	  8'h95:begin
	  		spi2_read_addr = 2'h2;
			cs_read_spi2 = 1; end
	  8'h96:begin
	  		spi2_read_addr = 2'h3;
			cs_read_spi2 = 1; end
	  default: begin
	  		spi2_read_addr = 2'h0;
			cs_read_spi2 = 0; end
	endcase
end



//CAN_ESFR & CAN2_ESFR  selected by EO[7] named CANSEL
reg		[7:0] can_read_addr;
reg		[7:0] can_write_addr;
wire		  cs_can;
reg			  cs_read_can;
reg			  cs_write_can;
wire    [7:0] can_data_out;
wire		  can_we;

wire		  can_rx_i;
wire		  can_tx_o;

reg			  can_tx_q;

wire		  can_tx_nen;

always@(posedge CLK, posedge RESET)
begin
	if(RESET)
		can_tx_q <= 1'b1;
	else
		can_tx_q <= can_tx_o;
end

assign	can_tx_nen = can_tx_o && can_tx_q;

assign	can_we = cs_write_can & SFRWE;			//when use mov 80h,F5H. at this time: cs = 1, we = 1, and 
assign	cs_can = cs_read_can | cs_write_can;    //write address decode as 0, so wrong register will be written
                                               	//so use can_we slove this problem 
can_top CAN_ESFR								 
(
	.clk_i(CLK),
	.rst_i(RESET),
	.cs_can_i(cs_can),

	.rd_i(SFRRE),
	.wr_i(can_we),
	.read_addr(can_read_addr),
	.write_addr(can_write_addr),
	.sfr_data_in(DESTIN_DO),
	.sfr_data_out(can_data_out),

	.rx_i(can_rx_i),	
	.tx_o(can_tx_o),
	.bus_off_on(),
	.irq_on(XINTR_SRC[8]),
	.clkout_o()
);

wire		  cs_can2;
reg			  cs_read_can2;
reg			  cs_write_can2;
wire    [7:0] can2_data_out;
wire		  can2_we;

wire		  can2_rx_i;
wire		  can2_tx_o;

reg			  can2_tx_q;

wire		  can2_tx_nen;

always@(posedge CLK, posedge RESET)
begin
	if(RESET)
		can2_tx_q <= 1'b1;
	else
		can2_tx_q <= can2_tx_o;
end

assign	can2_tx_nen = can2_tx_o && can2_tx_q;

assign	can2_we = cs_write_can2 & SFRWE;			//when use mov 80h,F5H. at this time: cs = 1, we = 1, and 
assign	cs_can2 = cs_read_can2 | cs_write_can2;    //write address decode as 0, so wrong register will be written
                                               	//so use can2_we slove this problem 
can_top CAN2_ESFR								 
(
	.clk_i(CLK),
	.rst_i(RESET),
	.cs_can_i(cs_can2),

	.rd_i(SFRRE),
	.wr_i(can2_we),
	.read_addr(can_read_addr),
	.write_addr(can_write_addr),
	.sfr_data_in(DESTIN_DO),
	.sfr_data_out(can2_data_out),

	.rx_i(can2_rx_i),	
	.tx_o(can2_tx_o),
	.bus_off_on(),
	.irq_on(XINTR_SRC[9]),
	.clkout_o()
);

//decode can write address
always @(*)
begin
  case(DESTIN_A)
	8'hD9:begin
		can_write_addr = 8'd0;
		cs_write_can = !CANSEL;
		cs_write_can2 = CANSEL;end
	8'hDA:begin
		can_write_addr = 8'd1;
		cs_write_can = !CANSEL;
		cs_write_can2 = CANSEL;end
	8'hDB:begin
		can_write_addr = 8'd2;
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hDC:begin
		can_write_addr = 8'd3;
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hDD:begin
		can_write_addr = 8'd4;
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hDE:begin
		can_write_addr = 8'd5;
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hDF:begin
		can_write_addr = 8'd6;
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hE1:begin
		can_write_addr = 8'd7;
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hE2:begin
		can_write_addr = 8'd10;
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hE3:begin
		can_write_addr = 8'd11;
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hE4:begin
		can_write_addr = 8'd12;
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hE5:begin
		can_write_addr = 8'd13;
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hE6:begin
		can_write_addr = 8'd14;
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hE7:begin
		can_write_addr = 8'd15;
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hE9:begin
		can_write_addr = 8'd16;
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hEA:begin
		can_write_addr = 8'd17;
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hEB:begin
		can_write_addr = 8'd18;
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hEC:begin
		can_write_addr = 8'd19;
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hED:begin
		can_write_addr = 8'd20;
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hEE:begin
		can_write_addr = 8'd21;	
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hEF:begin
		can_write_addr = 8'd22;	
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hF1:begin
		can_write_addr = 8'd23;	
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hF2:begin
		can_write_addr = 8'd24;	
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hF3:begin
		can_write_addr = 8'd25;	
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hF4:begin
		can_write_addr = 8'd26;	
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hF5:begin
		can_write_addr = 8'd27;	
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hF6:begin
		can_write_addr = 8'd28;	
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hF7:begin
		can_write_addr = 8'd29;	
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	8'hFA:begin
		can_write_addr = 8'd31;	
		cs_write_can = !CANSEL; 
		cs_write_can2 = CANSEL;end
	default:begin					
		can_write_addr = 8'd0;		
		cs_write_can = 0; 
		cs_write_can2 =0;end		
  endcase
end

//decode can read address
always @(*)
begin
  case({1'b1,SFRSA})
	8'hD9:begin
		can_read_addr = 8'd0;
		cs_read_can = !CANSEL;
		cs_read_can2 = CANSEL;end
	8'hDA:begin
		can_read_addr = 8'd1;
		cs_read_can = !CANSEL;
		cs_read_can2 = CANSEL;end
	8'hDB:begin
		can_read_addr = 8'd2;
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hDC:begin
		can_read_addr = 8'd3;
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hDD:begin
		can_read_addr = 8'd4;
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hDE:begin
		can_read_addr = 8'd5;
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hDF:begin
		can_read_addr = 8'd6;
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hE1:begin
		can_read_addr = 8'd7;
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hE2:begin
		can_read_addr = 8'd11;
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hE3:begin
		can_read_addr = 8'd11;
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hE4:begin
		can_read_addr = 8'd12;
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hE5:begin
		can_read_addr = 8'd13;
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hE6:begin
		can_read_addr = 8'd14;
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hE7:begin
		can_read_addr = 8'd15;
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hE9:begin
		can_read_addr = 8'd16;
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hEA:begin
		can_read_addr = 8'd17;
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hEB:begin
		can_read_addr = 8'd18;
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hEC:begin
		can_read_addr = 8'd19;
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hED:begin
		can_read_addr = 8'd20;
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hEE:begin
		can_read_addr = 8'd21;	
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hEF:begin
		can_read_addr = 8'd22;	
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hF1:begin
		can_read_addr = 8'd23;	
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hF2:begin
		can_read_addr = 8'd24;	
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hF3:begin
		can_read_addr = 8'd25;	
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hF4:begin
		can_read_addr = 8'd26;	
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hF5:begin
		can_read_addr = 8'd27;	
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hF6:begin
		can_read_addr = 8'd28;	
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hF7:begin
		can_read_addr = 8'd29;	
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	8'hFA:begin
		can_read_addr = 8'd31;	
		cs_read_can = !CANSEL; 
		cs_read_can2 = CANSEL;end
	default:begin					
		can_read_addr = 8'd0;		
		cs_read_can = 0; 
		cs_read_can2 =0;end		
  endcase
end

//i2c ESFR
reg		[2:0] i2c_read_addr;
reg		[2:0] i2c_write_addr;
wire		  cs_i2c;
reg			  cs_read_i2c;
reg			  cs_write_i2c;
wire	[7:0] i2c_data_out;
wire		  i2c_we;

wire		  i2c_scl_pad_i;
wire		  i2c_scl_pad_o;
wire		  i2c_scl_padoen_o;
wire		  i2c_sda_pad_i;
wire		  i2c_sda_pad_o;
wire		  i2c_sda_padoen_o;

reg			  i2c_scl_pad_o_q;
reg			  i2c_sda_pad_o_q;

assign i2c_we = cs_write_i2c & SFRWE;
assign cs_i2c = cs_read_i2c | cs_write_i2c;

i2c_master_top I2C_ESFR
(	.clk_i(CLK),
	.rst_i(RESET),
	.cs_i(cs_i2c),
	.write_adr_i(i2c_write_addr),
	.read_adr_i(i2c_read_addr),
	.dat_i(DESTIN_DO),
	.dat_o(i2c_data_out),
	.we_i(i2c_we),
	.re_i(SFRRE),
	.int_o(XINTR_SRC[10]),

	.scl_pad_i(i2c_scl_pad_i),
	.scl_pad_o(),
	.scl_padoen_o(i2c_scl_pad_o),
	.sda_pad_i(i2c_sda_pad_i),
	.sda_pad_o(),
	.sda_padoen_o(i2c_sda_pad_o) 
);	

//gegerate delay signal
always @(posedge CLK, posedge RESET)
begin
	if (RESET)
	begin
		i2c_scl_pad_o_q <= 1;
		i2c_sda_pad_o_q <= 1;
	end
	else
	begin
		i2c_scl_pad_o_q <= i2c_scl_pad_o;
		i2c_sda_pad_o_q <= i2c_sda_pad_o;
	end
end

assign	i2c_scl_padoen_o = i2c_scl_pad_o && i2c_scl_pad_o_q;
assign	i2c_sda_padoen_o = i2c_sda_pad_o && i2c_sda_pad_o_q;

//decode i2c write address
always @(*)
begin
  case(DESTIN_A)
	8'h9A:begin
		  i2c_write_addr = 3'h0;
		  cs_write_i2c = 1; end
	8'h9B:begin
		  i2c_write_addr = 3'h1;
		  cs_write_i2c = 1; end
	8'h9C:begin
		  i2c_write_addr = 3'h2;
		  cs_write_i2c = 1; end
	8'h9D:begin
		  i2c_write_addr = 3'h3;
		  cs_write_i2c = 1; end
	8'h9E:begin
		  i2c_write_addr = 3'h4;
		  cs_write_i2c = 1; end
	default: begin
		  i2c_write_addr = 3'h0;
		  cs_write_i2c = 0; end
  endcase
end

//decode i2c read address
always @(*)
begin
  case({1'b1,SFRSA})
	8'h9A:begin
		  i2c_read_addr = 3'h0;
		  cs_read_i2c = 1; end
	8'h9B:begin
		  i2c_read_addr = 3'h1;
		  cs_read_i2c = 1; end
	8'h9C:begin
		  i2c_read_addr = 3'h2;
		  cs_read_i2c = 1; end
	8'h9D:begin
		  i2c_read_addr = 3'h3;
		  cs_read_i2c = 1; end
	8'h9E:begin
		  i2c_read_addr = 3'h4;
		  cs_read_i2c = 1; end
	default: begin
		  i2c_read_addr = 3'h0;
		  cs_read_i2c = 0; end
  endcase
end

//pwm esfr
reg		[7:0] pwm_read_addr;
reg		[7:0] pwm_write_addr;
wire		  cs_pwm;
reg			  cs_read_pwm;
reg			  cs_write_pwm;
wire	[7:0] pwm_data_out;
wire		  pwm_we;

wire		  pwmout_0;
wire		  pwmout_1;
wire		  pwmout_2;
wire		  pwmout_3;

reg			  pwmout_0_q;
reg			  pwmout_1_q;
reg			  pwmout_2_q;
reg			  pwmout_3_q;

wire		  pwmout_0_nen;
wire		  pwmout_1_nen;
wire		  pwmout_2_nen;
wire		  pwmout_3_nen;

always @ (posedge CLK, posedge RESET)
begin
	if(RESET)
	begin
		pwmout_0_q <= 1'b1; 
		pwmout_1_q <= 1'b1;
        pwmout_2_q <= 1'b1;
        pwmout_3_q <= 1'b1;
	end
	else
	begin
		pwmout_0_q <= pwmout_0;
        pwmout_1_q <= pwmout_1;
        pwmout_2_q <= pwmout_2;
        pwmout_3_q <= pwmout_3;
	end
end

assign pwmout_0_nen = pwmout_0 && pwmout_0_q;
assign pwmout_1_nen = pwmout_1 && pwmout_1_q;
assign pwmout_2_nen = pwmout_2 && pwmout_2_q;
assign pwmout_3_nen = pwmout_3 && pwmout_3_q;

assign	pwm_we = cs_write_pwm & SFRWE;
assign	cs_pwm = cs_read_pwm | cs_write_pwm;

pwm PWM_ESFR
(	.clk(CLK),

	.rst(RESET),
	.cs(cs_pwm),
	.rd(SFRRE),
	.wr(pwm_we	),

	.write_addr(pwm_write_addr),
	.read_addr(pwm_read_addr),
	.data_in(DESTIN_DO),
	.data_out(pwm_data_out),

	.pwmout_0(pwmout_0),
	.pwmout_1(pwmout_1),
	.pwmout_2(pwmout_2),
	.pwmout_3(pwmout_3),

	.irq(XINTR_SRC[11])
);

//decode pwm write address
always@(*)
begin
  case(DESTIN_A)
  	8'hA3:begin
		  pwm_write_addr = 8'h0;
		  cs_write_pwm = 1;end
	8'hA4:begin
		  pwm_write_addr = 8'h1;
		  cs_write_pwm = 1;end
	8'hA5:begin
		  pwm_write_addr = 8'h2;
		  cs_write_pwm = 1;end
	8'hA6:begin
		  pwm_write_addr = 8'h3;
		  cs_write_pwm = 1;end
	8'hA7:begin
		  pwm_write_addr = 8'h4;
		  cs_write_pwm = 1;end
	8'hAA:begin
		  pwm_write_addr = 8'h5;
		  cs_write_pwm = 1;end
	8'hAB:begin
		  pwm_write_addr = 8'h6;
		  cs_write_pwm = 1;end
	8'hAC:begin
		  pwm_write_addr = 8'h7;
		  cs_write_pwm = 1;end
	8'hAD:begin
		  pwm_write_addr = 8'h8;
		  cs_write_pwm = 1;end
	8'hAE:begin
		  pwm_write_addr = 8'h9;
		  cs_write_pwm = 1;end
	8'hAF:begin
		  pwm_write_addr = 8'hA;
		  cs_write_pwm = 1;end
	8'hBA:begin
		  pwm_write_addr = 8'hB;
		  cs_write_pwm = 1;end
	8'hBB:begin
		  pwm_write_addr = 8'hC;
		  cs_write_pwm = 1;end
	8'hBC:begin
		  pwm_write_addr = 8'hD;
		  cs_write_pwm = 1;end
	8'hBD:begin
		  pwm_write_addr = 8'hE;
		  cs_write_pwm = 1;end
	8'hBE:begin
		  pwm_write_addr = 8'hF;
		  cs_write_pwm = 1;end
	8'hBF:begin
		  pwm_write_addr = 8'h10;
		  cs_write_pwm = 1;end
	default:begin
		  pwm_write_addr = 8'h0;
		  cs_write_pwm = 0;end
	endcase
end

//decode pwm read address
always@(*)
begin
  case({1'b1,SFRSA})
  	8'hA3:begin
		  pwm_read_addr = 8'h0;
		  cs_read_pwm = 1;end
	8'hA4:begin
		  pwm_read_addr = 8'h1;
		  cs_read_pwm = 1;end
	8'hA5:begin
		  pwm_read_addr = 8'h2;
		  cs_read_pwm = 1;end
	8'hA6:begin
		  pwm_read_addr = 8'h3;
		  cs_read_pwm = 1;end
	8'hA7:begin
		  pwm_read_addr = 8'h4;
		  cs_read_pwm = 1;end
	8'hAA:begin
		  pwm_read_addr = 8'h5;
		  cs_read_pwm = 1;end
	8'hAB:begin
		  pwm_read_addr = 8'h6;
		  cs_read_pwm = 1;end
	8'hAC:begin
		  pwm_read_addr = 8'h7;
		  cs_read_pwm = 1;end
	8'hAD:begin
		  pwm_read_addr = 8'h8;
		  cs_read_pwm = 1;end
	8'hAE:begin
		  pwm_read_addr = 8'h9;
		  cs_read_pwm = 1;end
	8'hAF:begin
		  pwm_read_addr = 8'hA;
		  cs_read_pwm = 1;end
	8'hBA:begin
		  pwm_read_addr = 8'hB;
		  cs_read_pwm = 1;end
	8'hBB:begin
		  pwm_read_addr = 8'hC;
		  cs_read_pwm = 1;end
	8'hBC:begin
		  pwm_read_addr = 8'hD;
		  cs_read_pwm = 1;end
	8'hBD:begin
		  pwm_read_addr = 8'hE;
		  cs_read_pwm = 1;end
	8'hBE:begin
		  pwm_read_addr = 8'hF;
		  cs_read_pwm = 1;end
	8'hBF:begin
		  pwm_read_addr = 8'h10;
		  cs_read_pwm = 1;end
	default:begin
		  pwm_read_addr = 8'h0;
		  cs_read_pwm = 0;end
	endcase
end


assign ESFRDI = {8{cs_read_spi}} & spi_data_out | 
				{8{cs_read_can}} & can_data_out |
				{8{cs_read_spi2}}& spi2_data_out|
				{8{cs_read_can2}}& can2_data_out|
				{8{cs_read_i2c}} & i2c_data_out |
				{8{cs_read_pwm}} & pwm_data_out |
				{8{cs_read_uart}}&uart_data_out;

endmodule
